<?php

namespace maoxuner\LaravelJsonRpc\Exceptions;

use Exception;
use Illuminate\Contracts\Debug\ExceptionHandler;
use Illuminate\Contracts\Support\Arrayable;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Support\MessageBag;
use Throwable;

abstract class BaseException extends Exception implements Arrayable
{
    /**
     * Custom error array (list/assoc)
     */
    protected array $data = [];

    /**
     * Fixed error structure
     */
    protected MessageBag $details;

    public function __construct(string $message = '', int $code = 0, ?Throwable $previous = null)
    {
        parent::__construct($message, $code, $previous);

        $this->details = new MessageBag;
    }

    public function fill(array $data): static
    {
        $this->data = $data;

        return $this;
    }

    public function merge($messages): static
    {
        $this->details->merge($messages);

        return $this;
    }

    public function add(string $key, string $message): static
    {
        $this->details->add($key, $message);

        return $this;
    }

    public function isEmpty(): bool
    {
        return $this->details->isEmpty();
    }

    public function isNotEmpty(): bool
    {
        return $this->details->isNotEmpty();
    }

    public function toArray()
    {
        $data = $this->data ?: $this->details->toArray();

        if (empty($data) && $previous = $this->getPrevious()) {
            $request = new Request;
            $request->headers->set('Accept', 'application/json');
            $response = app(ExceptionHandler::class)->render($request, $previous);
            if ($response instanceof JsonResponse) {
                $data = $response->getData(true);
            }
        }

        return $data;
    }
}
